package com.cloudkinto.service.platform.impl;

import cn.afterturn.easypoi.csv.entity.CsvExportParams;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.ListUtil;
import cn.hutool.core.date.DateUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.cloudkinto.common.RabbitQueueConstant;
import com.cloudkinto.common.RedisKeyConstants;
import com.cloudkinto.common.common.DateUtils;
import com.cloudkinto.common.constant.GlobalConstants;
import com.cloudkinto.common.constant.SysConstant;
import com.cloudkinto.common.exception.BizException;
import com.cloudkinto.common.utils.*;
import com.cloudkinto.common.utils.ali.AliOss;
import com.cloudkinto.common.utils.dict.StaticDict;
import com.cloudkinto.dao.*;
import com.cloudkinto.dto.platform.PlatOrderUpdateTimeDto;
import com.cloudkinto.entity.*;
import com.cloudkinto.enumType.operate.OperateTypeEnum;
import com.cloudkinto.service.consumer.vo.StockToPlatformConsumerReq;
import com.cloudkinto.service.consumer.vo.amazon.AmazonConsumerReq;
import com.cloudkinto.service.consumer.vo.amazon.AmazonItemConsumerReq;
import com.cloudkinto.service.consumer.vo.amazon.PlatStoreConsumerReq;
import com.cloudkinto.service.consumer.vo.amazon.fulfillment.*;
import com.cloudkinto.service.consumer.vo.amazon.inventory.*;
import com.cloudkinto.service.consumer.vo.order.PlatformOrderCancelReq;
import com.cloudkinto.service.consumer.vo.order.UpdateInventoryLessReq;
import com.cloudkinto.service.consumer.vo.orderSyncRecord.PlatformOrderSyncRecordReq;
import com.cloudkinto.service.order.PlatformOrderCopyService;
import com.cloudkinto.service.platform.sync.PlatformOrderSyncRecordService;
import com.cloudkinto.service.platform.*;
import com.cloudkinto.service.platform.sync.vo.SyncRecordItemReq;
import com.cloudkinto.service.platform.vo.AsyncFinishConsumerReq;
import com.cloudkinto.service.platform.vo.AsyncUpdateConsumerReq;
import com.cloudkinto.service.platform.vo.StockToPlatformRecordVo;
import com.cloudkinto.service.platform.vo.amazon.*;
import com.cloudkinto.service.platform.vo.amazon.stock.InventoryAmazonEntity;
import com.cloudkinto.service.platform.vo.store.StoreAmazonAddReq;
import com.cloudkinto.vo.stock.PlatformSkuStockDto;
import lombok.RequiredArgsConstructor;
import org.apache.commons.lang.StringUtils;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.DefaultTypedTuple;
import org.springframework.data.redis.core.ZSetOperations;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.File;
import java.math.BigDecimal;
import java.nio.charset.StandardCharsets;
import java.util.*;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

@Service
@Transactional(rollbackFor = Exception.class)//事务回滚
@RequiredArgsConstructor
public class PlatformOrderAmazonSyncServiceImpl extends AmazonBaseServiceImpl<PlatformOrderDao, PlatformOrderDo> implements PlatformOrderAmazonSyncService {
    private final PlatformStoreDao platformStoreDao;
    private final PlatformStoreService platformStoreService;
    private final PlatformOrderDao platformOrderDao;
    private final PlatformOrderService platformOrderService;
    private final RabbitTemplate rabbitTemplate;
    private final PlatformOrderProductDao platformOrderProductDao;
    private final PlatformProductService platformProductService;
    private final RakutenMarkRecordService rakutenMarkRecordService;
    private final RakutenMarkRecordOrderService rakutenMarkRecordOrderService;
    @Value("${gbc.auth.redirectURL}")
    private String redirectURL;
    @Value("${gbc.customer}")
    private String customer;
    private final PlatformOrderCopyService platformOrderCopyService;
    private final PlatformOrderSyncRecordDao platformOrderSyncRecordDao;
    private final PlatformOrderSyncRecordService platformOrderSyncRecordService;
    private final AsyncJobDao asyncJobDao;
    private final ProductStockDao productStockDao;
    @Value("${gbc.exportPath.omsFilePath}")
    private String omsFilePath;
    @Value("${gbc.uploadPath.omsFileUrl}")
    private String omsFileUrl;
    @Value("${gbc.uploadPath.fileUrl}")
    private String fileUrl;
    @Value("${gbc.uploadPath.filePath}")
    private String filePath;


    @Override
    public String updateAmazonOrdersHistory(Long storeId, String orderNumber) {
        PlatformStoreDo storeDo = platformStoreDao.selectById(storeId);
        if (storeDo == null || StringUtils.isBlank(storeDo.getSellerId())) {
            return ("店铺对应平台Token未绑定");
        }
        Date beginTime = null;
        Date endTime = null;
        Double time = redisTemplate.opsForZSet().score(RedisKeyConstants.orderSyncTimeSet_Amazon_History + customer, storeDo.getId());
        if (time == null) {
            beginTime = (DateUtils.passingDateYear(new Date(), -1));
        } else {
            beginTime = (new Date(time.longValue()));
        }
        endTime = (DateUtils.passingDateHour(beginTime, 2));
        long day = DateUtil.betweenDay(endTime, new Date(), true);
        if (day < 14) {
            return ("时间间隔不能小于14天");
        }
        //记录上次同步结束时间， 每次 同步 12小时数据
        redisTemplate.opsForZSet().add(RedisKeyConstants.orderSyncTimeSet_Amazon_History + customer, storeDo.getId(), endTime.getTime() - 1000);

        String nextToken = "";
        Map<String, Object> params = new HashMap<>();
        params.put("MarketplaceIds", StaticDict.PlatformOrder_Amazon_Market.getMarketplaceId(storeDo.getRegionCode()));
        String endPoint = StaticDict.PlatformOrder_Amazon_Market.getEndpoint(storeDo.getRegionCode());
        String accessToken = getRDTAccessToken(storeDo);
        if (StringUtils.isBlank(accessToken)) {
            redisTemplate.opsForZSet().add(RedisKeyConstants.orderSyncTimeSet_Amazon_History + customer, storeDo.getId(), beginTime.getTime());
            return "accessToken 获取失败";
        }
        if (StringUtils.isNotBlank(orderNumber)) {//最多50个；
            params.put("AmazonOrderIds", orderNumber);

        } else {
            params.put("LastUpdatedBefore", TimeUtils.formatDate(endTime, GlobalConstants.TIME_FORMAT_STR, "GMT"));
            params.put("LastUpdatedAfter", TimeUtils.formatDate(beginTime, GlobalConstants.TIME_FORMAT_STR, "GMT"));
        }
        List<OrdersEntitySP> orders = new ArrayList<>();
        do {
            if (StringUtils.isNotBlank(nextToken)) {
                params.put("NextToken", nextToken);
            }
            String result = AmazonUtil.spOrderList(endPoint + "/orders/v0/orders", accessToken, getAwsSTSSessionToken(storeDo.getRegionCode()), storeDo.getRegionCode(), params);
            JSONObject jsonObject = JSON.parseObject(result);
            if (jsonObject.getJSONArray("errors") != null) {
                log.error(jsonObject.getJSONArray("errors").toJSONString());
                //如果同步失败则 将上一次同步时间更新到以前
                redisTemplate.opsForZSet().add(RedisKeyConstants.orderSyncTimeSet_Amazon_History + customer, storeDo.getId(), beginTime.getTime());
                return (jsonObject.getJSONArray("errors").toJSONString());
            }
            //主表对象
            ListOrdersResultEntitySP orderReponse = JSONObject.parseObject(jsonObject.get("payload").toString(), ListOrdersResultEntitySP.class);
            orders.addAll(new ArrayList<>(orderReponse.getOrders().stream().filter(o -> !o.getOrderStatus().equals("Pending")).collect(Collectors.toList())));
            nextToken = orderReponse.getNextToken();
        } while (StringUtils.isNotBlank(nextToken));


        //组装
        //要插入的
        List<PlatformOrderCopyDo> platInertList = new ArrayList<>();
        for (OrdersEntitySP amzOrder : orders) {
            PlatformOrderCopyDo copyDo = new PlatformOrderCopyDo();
            copyDo.setCompanyId(storeDo.getCompanyId());
            copyDo.setStoreId(storeDo.getId());
            copyDo.setPlatformOrderNo(amzOrder.getAmazonOrderId());
            copyDo.setOrderTime(TimeUtils.getDateTime2(amzOrder.getPurchaseDate(), "Asia/Tokyo"));
            copyDo.setPlatformCode(storeDo.getPlatformCode());
            JSONObject order = JSONObject.parseObject(JSON.toJSONString(amzOrder));

            Map<String, Object> parametersMap = new HashMap<>();
            parametersMap.put("orderId", amzOrder.getAmazonOrderId());
            String orderItemsStr = AmazonUtil.spOrder(endPoint + "/orders/v0/orders/" + copyDo.getPlatformOrderNo() + "/orderItems", getAccessToken(storeDo),
                    getAwsSTSSessionToken(storeDo.getRegionCode()), storeDo.getRegionCode(), parametersMap);
            JSONObject jsonObject = JSON.parseObject(orderItemsStr);
            if (jsonObject == null) {
                return "Amazon历史订单同步子表空";
            }
            if (jsonObject.getJSONArray("errors") != null) {
                return (storeDo.getStoreName() + " 历史同步亚马逊订单 item 失败：" + jsonObject.getJSONArray("errors").getString(0));
            }
            order.put("items", jsonObject.getJSONObject("payload").toString());
            copyDo.setOrderMsg(order.toJSONString());
            platInertList.add(copyDo);
        }
        platformOrderCopyService.batchInsert(platInertList);
        return "";
    }



    @Override
    public String updateAmazonOrders(PlatStoreConsumerReq req)  {
        PlatformStoreDo platformStoreDo = platformStoreDao.selectById(req.getStoreId());
        return this.updateAmazonOrders(platformStoreDo, req.getBeginTime(), req.getEndTime(), req.getOrderNumbers(), false, req.getSyncId());
    }


    @Override
    public void platOrderAmazonSync() {
        List<PlatformStoreDo> storeDoList = platformStoreDao.selectList(new LambdaQueryWrapper<PlatformStoreDo>().eq(PlatformStoreDo::getPlatformCode, "amazon")
                .eq(PlatformStoreDo::getAuthSyncStatus, 1).isNotNull(PlatformStoreDo::getAppSecret));
        Map<Long, Long> storeRecordIdMap = new HashMap<>();
        for (PlatformStoreDo storeDo : storeDoList) {
            PlatformOrderSyncRecordDo recordDo = new PlatformOrderSyncRecordDo(storeDo.getPlatformCode(), storeDo.getId(), 1, 0, 0, new Date(), null, storeDo.getCompanyId());
            platformOrderSyncRecordDao.insert(recordDo);
            storeRecordIdMap.put(storeDo.getId(), recordDo.getId());
        }
        for (PlatformStoreDo platformStoreDo : storeDoList) {
            Long syncRecordId = storeRecordIdMap.get(platformStoreDo.getId());
            if (syncRecordId == null) {
                continue;
            }
            PlatStoreConsumerReq consumerReq = new PlatStoreConsumerReq(platformStoreDo.getId(), null, null, null, false, syncRecordId);
            rabbitTemplate.convertAndSend(RabbitQueueConstant.PlatformStore_Amazon, JSON.toJSONString(consumerReq));
        }
    }

    @Override
    public String testGetOrderByNumber(String orderNumber, Date beginTime, Date endTime, Long storeId) {
        List<PlatformStoreDo> storeDoList = new ArrayList<>();
        if (storeId == null) {
            storeDoList = platformStoreDao.selectList(new LambdaQueryWrapper<PlatformStoreDo>().eq(PlatformStoreDo::getPlatformCode, "rakuten")
                    .eq(PlatformStoreDo::getAuthSyncStatus, 1).isNotNull(PlatformStoreDo::getAppSecret));
        }
        else {
            PlatformStoreDo platformStoreDo = platformStoreDao.selectById(storeId);
            if (platformStoreDo == null || platformStoreDo.getAuthSyncStatus() != 1) {
                return "未授权";
            }
            storeDoList.add(platformStoreDo);
        }
        String msg = "多店铺异步同步 请稍候查看 务重复点击";
        for (PlatformStoreDo storeDo : storeDoList) {
            if (storeDoList.size() == 1) {
                msg = this.updateAmazonOrders(storeDo, beginTime, endTime, orderNumber, false, null);
            } else {
                PlatStoreConsumerReq consumerReq = new PlatStoreConsumerReq(storeDo.getId(), beginTime, endTime, orderNumber, false, null);
                rabbitTemplate.convertAndSend(RabbitQueueConstant.PlatformStore_Amazon, JSON.toJSONString(consumerReq));
            }
        }
        return msg;
    }

    @Override
    public Map<String, Object> getOrderByNumber(String orderNumber, Long storeId) {
        PlatformStoreDo storeDo = platformStoreDao.selectById(storeId);
        Map<String, Object> resultMap = new HashMap<>();
        String nextToken = "";
        Map<String, Object> params = new HashMap<>();
        params.put("MarketplaceIds", StaticDict.PlatformOrder_Amazon_Market.getMarketplaceId(storeDo.getRegionCode()));
        String endPoint = StaticDict.PlatformOrder_Amazon_Market.getEndpoint(storeDo.getRegionCode());
        String accessToken = getRDTAccessToken(storeDo);
        if (StringUtils.isBlank(accessToken)) {
            resultMap.put("code", 500);
            resultMap.put("msg", "accessToken 获取失败");
            return resultMap;
        }
        //最多50个；
        params.put("AmazonOrderIds", orderNumber);
        List<OrdersEntitySP> orders = new ArrayList<>();
        do {
            if (StringUtils.isNotBlank(nextToken)) {
                params.put("NextToken", nextToken);
            }
            String result = AmazonUtil.spOrderList(endPoint + "/orders/v0/orders", accessToken, getAwsSTSSessionToken(storeDo.getRegionCode()), storeDo.getRegionCode(), params);
            JSONObject jsonObject = JSON.parseObject(result);
            if (jsonObject.getJSONArray("errors") != null) {
                log.info(storeDo.getStoreCode() + "手动" + "列表同步错误：" + jsonObject.getJSONArray("errors").toJSONString());
                resultMap.put("code", 500);
                resultMap.put("msg", jsonObject.getJSONArray("errors").toJSONString());
            }
            //主表对象
            ListOrdersResultEntitySP orderReponse = JSONObject.parseObject(jsonObject.get("payload").toString(), ListOrdersResultEntitySP.class);
            orders.addAll(new ArrayList<>(orderReponse.getOrders().stream().filter(o -> !o.getOrderStatus().equals("Pending")).collect(Collectors.toList())));
            nextToken = orderReponse.getNextToken();
        } while (StringUtils.isNotBlank(nextToken));
        resultMap.put("orders", orders);
        resultMap.put("code", 200);

        Map<String, Object> parametersMap = new HashMap<>();
        for (OrdersEntitySP toUpdateItem : orders) {
            parametersMap.put("orderId", toUpdateItem.getAmazonOrderId());
            String orderItemsStr = AmazonUtil.spOrder(endPoint + "/orders/v0/orders/" + toUpdateItem.getAmazonOrderId() + "/orderItems", getAccessToken(storeDo),
                    getAwsSTSSessionToken(storeDo.getRegionCode()), storeDo.getRegionCode(), parametersMap);
            JSONObject jsonObject = JSON.parseObject(orderItemsStr);
            if (jsonObject == null) continue;
            if (jsonObject.getJSONArray("errors") != null) {
                //{"code":"QuotaExceeded","details":"","message":"You exceeded your quota for the requested resource."}
                JSONObject string = jsonObject.getJSONArray("errors").getJSONObject(0);
                log.info(storeDo.getStoreName() + " 手动同步亚马逊订单 item 失败：" + string.toJSONString());
                if (Objects.equals(string.getString("code"), "QuotaExceeded")) {
                    break;
                }
            } else {
                //同步成功
                OrderItemsSPEntity itemsResponse = JSON.parseObject(jsonObject.getJSONObject("payload").toString(), OrderItemsSPEntity.class);
                resultMap.put("item", itemsResponse);
            }
        }
        return resultMap;
    }

    @Override
    public String updateAmazonOrders(PlatformStoreDo storeDo, Date beginTime, Date endTime, String orderNumber, boolean isHistory, Long syncId) {
        if (storeDo == null || StringUtils.isBlank(storeDo.getSellerId())) {
            return ("店铺对应平台Token未绑定");
        }
        String quotaExceededKey = "Amazon_orders_QuotaExceeded_" +customer + "_" + storeDo.getId();
        if (Boolean.TRUE.equals(redisTemplate.hasKey(quotaExceededKey))) {
            return "订单列表接口：quotaExceededKey";
        }
        boolean flag = beginTime == null && StringUtils.isBlank(orderNumber);
        if (flag) {
            Double time = redisTemplate.opsForZSet().score(RedisKeyConstants.orderSyncTimeSet_Amazon+ customer, storeDo.getId());
            long currency = System.currentTimeMillis();
            if (!(time == null || (currency - time) >= 60 * 5 * 1000)) {
//                return "同步频率过快(5分钟同步一次)";
            }
            //无上次同步时间 或者 上次同步时间在10分钟之前
            redisTemplate.opsForZSet().add(RedisKeyConstants.orderSyncTimeSet_Amazon+ customer, storeDo.getId(), currency - 5 * 1000);
            if (time == null) {
                beginTime = DateUtils.passingDateHour(new Date(), -14);
            } else {
                //往前缩20分钟
                beginTime = new Date(time.longValue() - 60 * 1000 * 21);
            }
            long l = DateUtil.betweenDay(beginTime, new Date(), true);
            if (l > 2) {
                beginTime = (DateUtils.passingDate(new Date(), -2));
            }
        }
        String nextToken = "";
        Map<String, Object> params = new HashMap<>();
        params.put("MarketplaceIds", StaticDict.PlatformOrder_Amazon_Market.getMarketplaceId(storeDo.getRegionCode()));
        String endPoint = StaticDict.PlatformOrder_Amazon_Market.getEndpoint(storeDo.getRegionCode());
        String accessToken = getRDTAccessToken(storeDo);
        if (StringUtils.isBlank(accessToken)) {
            if (flag) {
                redisTemplate.opsForZSet().add(RedisKeyConstants.orderSyncTimeSet_Amazon+ customer, storeDo.getId() ,  beginTime.getTime());
            }
            return "accessToken 获取失败";
        }
        if (!flag) {
            if (StringUtils.isNotBlank(orderNumber)) {//最多50个；
                params.put("AmazonOrderIds", orderNumber);
            }
            else {
                //判断日期跨度不能太长
            params.put("CreatedBefore", TimeUtils.formatDate(endTime, GlobalConstants.TIME_FORMAT_STR, "GMT"));
            params.put("CreatedAfter", TimeUtils.formatDate(beginTime, GlobalConstants.TIME_FORMAT_STR, "GMT"));
            }
        } else {
            params.put("LastUpdatedAfter", TimeUtils.formatDate(beginTime, GlobalConstants.TIME_FORMAT_STR, "GMT"));
        }
        //告诉他正在处理
        rabbitTemplate.convertAndSend(RabbitQueueConstant.PlatformOrder_SyncRecord_Update, JSON.toJSONString(new PlatformOrderSyncRecordReq(syncId, 1, new Date(), beginTime, endTime)));

        List<OrdersEntitySP> orders = new ArrayList<>();
        String error = null;
        do {
            if (StringUtils.isNotBlank(nextToken)) {
                params.put("NextToken", nextToken);
            }
            log.info("amazon 店铺：:" + storeDo.getStoreCode() + "同步订单; 请求参数：\r\n" + JSON.toJSONString(params));
            String result = AmazonUtil.spOrderList(endPoint + "/orders/v0/orders", accessToken, getAwsSTSSessionToken(storeDo.getRegionCode()), storeDo.getRegionCode(), params);
            log.info("amazon 店铺：:" + storeDo.getStoreCode() + "同步订单; 请求响应：\r\n" + result);
            JSONObject jsonObject = JSON.parseObject(result);
            if (jsonObject.getJSONArray("errors") != null) {
                log.info(storeDo.getStoreCode() +(flag ? "自动" : "手动") +"列表同步错误：" +jsonObject.getJSONArray("errors").toJSONString());
                //如果同步失败则 将上一次同步时间更新到以前
                if (flag) {//自动
                    if (orders.isEmpty()) {
                        redisTemplate.opsForZSet().add(RedisKeyConstants.orderSyncTimeSet_Amazon + customer, storeDo.getId(), beginTime.getTime());
                    }
                    else {
                        //获取orders 最大的最后更新时间
                        orders.sort((o1, o2) -> {
                            try {
                                Date o1Time = TimeUtils.getDateTime2(o1.getLastUpdateDate(), "Asia/Tokyo");
                                Date o2Time = TimeUtils.getDateTime2(o2.getLastUpdateDate(), "Asia/Tokyo");
                                return o2Time.compareTo(o1Time);
                            } catch (Exception e) {
                                // 处理异常，例如记录日志
                                e.printStackTrace();
                                // 返回 0 表示不排序，或者根据业务需求返回其他值
                                return 0;
                            }
                        });
                        Date platUpdateTIme = TimeUtils.getDateTime2(orders.get(0).getLastUpdateDate(), "Asia/Tokyo");
                        redisTemplate.opsForZSet().add(RedisKeyConstants.orderSyncTimeSet_Amazon + customer, storeDo.getId(), platUpdateTIme.getTime());
                    }
                }
                JSONObject string = jsonObject.getJSONArray("errors").getJSONObject(0);
                if (Objects.equals(string.getString("code"), "QuotaExceeded")) {
                    redisTemplate.opsForValue().set(quotaExceededKey, true, 60 * 8, TimeUnit.SECONDS);
                }
                error = string.toJSONString();
//                return (jsonObject.getJSONArray("errors").toJSONString());
                break;
            }
            //主表对象
            ListOrdersResultEntitySP orderReponse = JSONObject.parseObject(jsonObject.get("payload").toString(), ListOrdersResultEntitySP.class);
            orders.addAll(new ArrayList<>(orderReponse.getOrders().stream().filter(o -> !("AFN".equals(o.getFulfillmentChannel()) && o.getOrderStatus().equals("Pending"))).collect(Collectors.toList())));
            nextToken = orderReponse.getNextToken();
        } while (StringUtils.isNotBlank(nextToken));

        //获取这些订单的 最近更新时间
        List<String> platformOrders = orders.stream().map(OrdersEntitySP::getAmazonOrderId).collect(Collectors.toList());
        Map<String, PlatOrderUpdateTimeDto> orderMap = new HashMap<>();
        if (!platformOrders.isEmpty()) {
            List<List<String>> partition = ListUtil.partition(platformOrders, 5000);
            for (List<String> list : partition) {
                List<PlatOrderUpdateTimeDto> platOrder = platformOrderDao.getPlatOrder(list, storeDo.getId(), "amazon");
                orderMap.putAll(platOrder.stream().collect(Collectors.toMap(PlatOrderUpdateTimeDto::getPlatformOrderNo,
                        i -> i, (i1, i2) -> i1)));
            }
        }

        //组装
        //要插入的
        List<PlatformOrderDo> platInertList = new ArrayList<>();
        //要更新 子表的的
        List<OrderIdEntity> toUpdateItemOrderIds = new ArrayList<>();
        List<String> itemConsumer = new ArrayList<>();
        List<String> cancelOrderNos = new ArrayList<>();
        for (OrdersEntitySP amzOrder : orders) {//区分 afn mfn
            Date platUpdateTIme = TimeUtils.getDateTime2(amzOrder.getLastUpdateDate(), "Asia/Tokyo");
            PlatOrderUpdateTimeDto oldUpdateTime = orderMap.get(amzOrder.getAmazonOrderId());
            //如果最近更新时间 和子表都同步下来了 就不需要在操作了
            if (oldUpdateTime != null && Objects.equals(oldUpdateTime.getLastUpdateDate().getTime(), platUpdateTIme.getTime())) {
                //更新日期相等
                if (oldUpdateTime.getItemCount() == 0) {
                    //子表未同步
                    toUpdateItemOrderIds.add(new OrderIdEntity(oldUpdateTime.getId(), oldUpdateTime.getPayTime(), amzOrder.getAmazonOrderId(), oldUpdateTime.getFulfillmentChannel()));
                }
                continue;
            }
            PlatformOrderDo orderDo  = new PlatformOrderDo();
            orderDo.setCompanyId(storeDo.getCompanyId());
            orderDo.setTenantId(storeDo.getTenantId());
            orderDo.setPlatformCode(storeDo.getPlatformCode());
            orderDo.setStoreId(storeDo.getId());
            orderDo.setSite(storeDo.getSite());
            orderDo.setOrderTime(TimeUtils.getDateTime2(amzOrder.getPurchaseDate(), "Asia/Tokyo"));
            orderDo.setPayTime(TimeUtils.getDateTime2(amzOrder.getPurchaseDate(), "Asia/Tokyo"));
            orderDo.setLastUpdateDate(platUpdateTIme);
            orderDo.setPlatformOrderNo(amzOrder.getAmazonOrderId());
            orderDo.setReserveFlag(0);
            orderDo.setFulfillmentChannel(amzOrder.getFulfillmentChannel());
            //预约单
            if ("Preorder".equals(amzOrder.getOrderType())) {
                orderDo.setReserveFlag(1);
            }
            if (StringUtils.isNotBlank(amzOrder.getLatestShipDate())) {
                orderDo.setReserveEndTime(TimeUtils.getDateTime2(amzOrder.getLatestShipDate(), "Asia/Tokyo"));
            }
            if (StringUtils.isNotBlank(amzOrder.getEarliestShipDate())) {
                orderDo.setReserveBeginTime(TimeUtils.getDateTime2(amzOrder.getEarliestShipDate(), "Asia/Tokyo"));
            }
            if ("Canceled".equals(amzOrder.getOrderStatus())) {
                orderDo.setStatus(StaticDict.Platform_Order_Status.Four.getValue());
                orderDo.setCancelWay(0);
            }
            else if ("Shipped".equals(amzOrder.getOrderStatus())) {
                orderDo.setStatus(StaticDict.Platform_Order_Status.Three.getValue());
                orderDo.setShipTime(TimeUtils.getDateTime2(amzOrder.getLastUpdateDate(), "Asia/Tokyo"));
//                orderDo.setMarkShipmentStatus(4);
            }
            else if ("Pending".equals(amzOrder.getOrderStatus()) && "MFN".equals(amzOrder.getFulfillmentChannel())) {
                orderDo.setStatus(StaticDict.Platform_Order_Status.Five.getValue());
                orderDo.setExceptionCause("支付确认中");
            }
            else {
                if (oldUpdateTime == null || StaticDict.Platform_Order_Status.Five.getValue().equals(oldUpdateTime.getStatus())) {
                    orderDo.setStatus(StaticDict.Platform_Order_Status.Zero.getValue());
                }
            }
            try {
                if ("Scheduled".equals(amzOrder.getShipmentServiceLevelCategory()) && amzOrder.getLatestDeliveryDate() != null && amzOrder.getEarliestDeliveryDate() != null) {
                    //指定配达
                    Date latestDeliverDate = TimeUtils.getDateTime2(amzOrder.getLatestDeliveryDate(), "Asia/Tokyo");
                    orderDo.setDeliveryDate(DateUtils.dateFormatToString(latestDeliverDate));
                    Date earliestDeliverDate = TimeUtils.getDateTime2(amzOrder.getEarliestDeliveryDate(), "Asia/Tokyo");
                    String deliverTimeName = TimeUtils.formatDate(earliestDeliverDate, "HH") + "-" + TimeUtils.formatDate(latestDeliverDate, "HH");
                    orderDo.setDeliveryTimeName(deliverTimeName);
                    orderDo.setReserveFlag(2);
                }
            } catch (Exception e) {
                e.printStackTrace();
            }

            OrdersEntitySP.ShippingAddressEntity shippingAddress = amzOrder.getShippingAddress();
            //收货人信息
            if (shippingAddress != null) {
                orderDo.setReceiver(shippingAddress.getName());
                orderDo.setTelephone(shippingAddress.getPhone());
                orderDo.setCountryRegionCode(shippingAddress.getCountryCode());
                orderDo.setProvinceCode(null);
                orderDo.setProvinceName(null);
                orderDo.setDistrict(shippingAddress.getStateOrRegion());
                orderDo.setPostcode(shippingAddress.getPostalCode());
                orderDo.setHouseNum("");
                orderDo.setCityCode(shippingAddress.getCity());
                if (StringUtils.isBlank(orderDo.getCityCode()) && StringUtils.isNotBlank(shippingAddress.getAddressLine1()) && shippingAddress.getAddressLine1().length() >= 3) {
                    String addr1 = shippingAddress.getAddressLine1();
                    int index1 = addr1.indexOf("村");
                    int index2 = addr1.indexOf("市");
                    int index3 = addr1.indexOf("区");
                    int index4 = addr1.indexOf("郡");
                    int index5 = addr1.indexOf("町");
                    List<Integer> indexList = new ArrayList<>();
                    if (index1 != -1) {
                        indexList.add(index1);
                    }
                    if (index2 != -1) {
                        indexList.add(index2);
                    }
                    if (index3 != -1) {
                        indexList.add(index3);
                    }
                    if (index4 != -1) {
                        indexList.add(index4);
                    }
                    if (index5 != -1) {
                        indexList.add(index5);
                    }
                    Collections.sort(indexList);
                    if (indexList.isEmpty()) {
                        orderDo.setCityCode("");
                        orderDo.setAddressOne(addr1);
                    } else {
                        int firstIndex = indexList.get(0) < 1 ? indexList.get(0) + 1 : indexList.get(0);
                        orderDo.setCityCode(addr1.substring(0, firstIndex + 1));
                        orderDo.setAddressOne(addr1.substring(firstIndex + 1));
                    }
                }
                else {
                    orderDo.setAddressOne(shippingAddress.getAddressLine1());
                }
                orderDo.setAddressTwo(shippingAddress.getAddressLine2());
                orderDo.setAddressTri(shippingAddress.getAddressLine3());
            }
            //发件人信息
            if (amzOrder.getBuyerInfo() != null) {
                orderDo.setBuyerName(amzOrder.getBuyerInfo().getBuyerName());
                orderDo.setBuyerEmail(amzOrder.getBuyerInfo().getBuyerEmail());
            }
            //总金额
            if (amzOrder.getOrderTotal() != null) {
                orderDo.setTotalAmount(BigDecimal.valueOf(amzOrder.getOrderTotal().getAmount()));
                orderDo.setCurrencyCode(amzOrder.getOrderTotal().getCurrencyCode());
            }
            if (oldUpdateTime != null) {
                orderDo.setId(oldUpdateTime.getId());
                platformOrderDao.updateById(orderDo);
                //默认更新时 不同步子表
                if (Objects.equals(orderDo.getStatus(), 4) && !Objects.equals(oldUpdateTime.getStatus(), 4)) {
                    cancelOrderNos.add(orderDo.getPlatformOrderNo());
                }
            }
            else {
                platInertList.add(orderDo);
            }
        }
        if (!platInertList.isEmpty()) {
            platformOrderDao.insertPlatformOrder(platInertList);
            for (PlatformOrderDo orderDo : platInertList) {
                if (!itemConsumer.contains(orderDo.getPlatformOrderNo())) {
                    itemConsumer.add(orderDo.getPlatformOrderNo());
                    toUpdateItemOrderIds.add(new OrderIdEntity(orderDo.getId(), orderDo.getPayTime(), orderDo.getPlatformOrderNo(), orderDo.getFulfillmentChannel()));
                }
            }
        }
        //获取近14天 没有同步子表的数据
        List<PlatOrderUpdateTimeDto> platOrder = platformOrderDao.getPlatOrder(null, storeDo.getId(), "amazon");
        for (PlatOrderUpdateTimeDto i : platOrder) {
            if (i.getStatus() == StaticDict.Platform_Order_Status.Four.getValue() || StaticDict.Platform_Order_Status.Three.getValue().equals(i.getStatus())) {//已取消的过滤 占用次数
                continue;
            }
            if (!itemConsumer.contains(i.getPlatformOrderNo())) {
                itemConsumer.add(i.getPlatformOrderNo());
                toUpdateItemOrderIds.add(new OrderIdEntity(i.getId(), i.getPayTime(), i.getPlatformOrderNo(), i.getFulfillmentChannel()));
            }
        }
        toUpdateItemOrderIds.sort(Comparator.<OrderIdEntity, Integer>comparing(i -> {
            if ("MFN".equals(i.getFulfillmentChannel())) return -1;
            if ("AFN".equals(i.getFulfillmentChannel())) return 1;
            return 0;
        }).thenComparing(OrderIdEntity::getPayTime, Comparator.nullsLast(Date::compareTo)));
//        for (List<OrderIdEntity> orderIdEntities : ListUtil.partition(toUpdateItemOrderIds, 1)) {
//            //再交给rabbitMq 去更新子表
//            rabbitTemplate.convertAndSend(RabbitQueueConstant.PlatformOrder_Amazon, JSON.toJSONString(new AmazonConsumerReq(orderIdEntities, storeDo)));
//        }
        rabbitTemplate.convertAndSend(RabbitQueueConstant.PlatformOrder_Amazon, JSON.toJSONString(new AmazonConsumerReq(toUpdateItemOrderIds, storeDo, flag)));

        List<SyncRecordItemReq> items = platInertList.stream().map(i -> new SyncRecordItemReq(i.getId(), i.getPlatformOrderNo(), storeDo.getId(), storeDo.getCompanyId())).collect(Collectors.toList());
        if (StringUtils.isBlank(error)) {
            //完成
            rabbitTemplate.convertAndSend(RabbitQueueConstant.PlatformOrder_SyncRecord_Update, JSON.toJSONString(new PlatformOrderSyncRecordReq(syncId, 2, new Date(), null, null, platInertList.size(), items)));
        }
        else {
            rabbitTemplate.convertAndSend(RabbitQueueConstant.PlatformOrder_SyncRecord_Update, JSON.toJSONString(new PlatformOrderSyncRecordReq(syncId, 3, new Date(), null, error, platInertList.size(), items)));
        }
        if (!cancelOrderNos.isEmpty()) {
            rabbitTemplate.convertAndSend(RabbitQueueConstant.PlatformOrder_CancelForBound, JSON.toJSONString(new PlatformOrderCancelReq(storeDo.getId(), cancelOrderNos)));
        }
        return "";
    }

    @Override
    public void consumerUpdateAmazonItems(AmazonConsumerReq req) {
        String quotaExceededKey = "Amazon_orderItems_QuotaExceeded_" +customer + "_" + req.getStoreDo().getId();
        if (Boolean.TRUE.equals(redisTemplate.hasKey(quotaExceededKey))) {
            return;
        }
        //QuotaExceeded 放入缓存避免重复请求
        PlatformStoreDo storeDo = req.getStoreDo();
        String endPoint = StaticDict.PlatformOrder_Amazon_Market.getEndpoint(storeDo.getRegionCode());
        Map<String, Object> parametersMap = new HashMap<>();
        List<PlatformOrderProductDo> platItems = new ArrayList<>();
        Map<Long, String> platformSkuMap = new HashMap<>();
        //根据id 去重
        req.getToUpdateItemOrderIds().stream().filter(i -> i.getId() != null).collect(Collectors.groupingBy(OrderIdEntity::getId)).forEach((id, list) -> {
            if (list.size() > 1) {
                req.getToUpdateItemOrderIds().removeAll(list.subList(1, list.size()));
            }
        });
        for (OrderIdEntity toUpdateItem : req.getToUpdateItemOrderIds()) {
            if (toUpdateItem.getId() == null) {
                continue;
            }
            parametersMap.put("orderId", toUpdateItem.getPlatformOrderNo());
            String orderItemsStr = AmazonUtil.spOrder(endPoint + "/orders/v0/orders/" +toUpdateItem.getPlatformOrderNo() + "/orderItems", getAccessToken(storeDo),
                    getAwsSTSSessionToken(storeDo.getRegionCode()), storeDo.getRegionCode(), parametersMap);
            JSONObject jsonObject = JSON.parseObject(orderItemsStr);
            if (jsonObject == null) continue;
            if (jsonObject.getJSONArray("errors") != null) {
                //{"code":"QuotaExceeded","details":"","message":"You exceeded your quota for the requested resource."}
                JSONObject string = jsonObject.getJSONArray("errors").getJSONObject(0);
                log.error(storeDo.getStoreName() + " 同步亚马逊订单 item 失败：" + string.toJSONString());
                if (Objects.equals(string.getString("code"), "QuotaExceeded")) {
                    redisTemplate.opsForValue().set(quotaExceededKey, true, 60 * 18, TimeUnit.SECONDS);
                    break;
                }
            }
            else {
                StringBuilder builder = new StringBuilder();
                //同步成功
                OrderItemsSPEntity itemsResponse = JSON.parseObject(jsonObject.getJSONObject("payload").toString(), OrderItemsSPEntity.class);
                for (OrderItemsSPEntity.OrderItemsEntity orderItem : itemsResponse.getOrderItems()) {
                    PlatformOrderProductDo platItem = new PlatformOrderProductDo();
                    platItem.setOrderId(toUpdateItem.getId());
                    platItem.setPlatformOrderNo(toUpdateItem.getPlatformOrderNo());
                    platItem.setPlatformSku(orderItem.getSellerSKU());
                    platItem.setItemId(orderItem.getOrderItemId());
                    platItem.setPlatformProductName(orderItem.getTitle());
                    platItem.setPlatformQty(orderItem.getQuantityOrdered());
                    platItem.setSkuType(1);
                    if (orderItem.getItemPrice() != null) {
                        platItem.setItemAmount(BigDecimal.valueOf(orderItem.getItemPrice().getAmount()));
                        platItem.setCurrencyCode(orderItem.getItemPrice().getCurrencyCode());
                    }
                    if (StringUtils.isNotBlank(builder.toString())) {
                        builder.append(";");
                    }
                    builder.append(platItem.getPlatformSku()).append("*").append(platItem.getPlatformQty());
                    platItems.add(platItem);
                }
                if (StringUtils.isNotBlank(builder.toString())) {
                    platformSkuMap.put(toUpdateItem.getId(), builder.toString());
                }
            }
        }

        if (!platItems.isEmpty()) {
            //匹配系统sku
            platformOrderService.matchSystemSku(platItems, storeDo.getId(), storeDo.getCompanyId(), storeDo.getTenantId());
            //先删除
            platformOrderProductDao.delete(new LambdaQueryWrapper<PlatformOrderProductDo>().in(PlatformOrderProductDo::getOrderId, platItems.stream().map(PlatformOrderProductDo::getOrderId).collect(Collectors.toList())));
            platformOrderProductDao.insertPlatformOrderItems(platItems);
        }
        Map<Long, List<PlatformOrderProductDo>> skuMap = platItems.stream().filter(i -> StringUtils.isNotBlank(i.getSku())).collect(Collectors.groupingBy(PlatformOrderProductDo::getOrderId));
        for (Long orderId : platformSkuMap.keySet()) {
            String platformSku = platformSkuMap.get(orderId);
            if (platformSku.length() > 100) {
                platformSku = platformSku.substring(0, 100);
            }
            LambdaUpdateWrapper<PlatformOrderDo> updateWrapper = new LambdaUpdateWrapper<PlatformOrderDo>();
            updateWrapper.set(PlatformOrderDo::getPlatformSku, platformSku)
                    .eq(PlatformOrderDo::getId, orderId);
            if (skuMap.get(orderId) != null) {
                StringBuilder sku = new StringBuilder();
                for (PlatformOrderProductDo productDo : skuMap.get(orderId)) {
                    if (StringUtils.isNotBlank(sku.toString())) {
                        sku.append(";");
                    }
                    sku.append(productDo.getSku()).append("*").append(productDo.getQty());
                }
                if (sku.length() > 100) {
                    sku = new StringBuilder(sku.substring(0, 100));
                }
                updateWrapper.set(PlatformOrderDo::getSku, sku.toString());
            }
            platformOrderDao.update(null, updateWrapper);
        }
        if (req.isFlag()) {
            rabbitTemplate.convertAndSend(RabbitQueueConstant.StockToPlatform_CreateStockToPlatformAfterSync, storeDo.getId()+"");
        }
    }

    protected String AUTHORIZESTATEKEY = "amazon_authorize_state_";



    /**
     * 亚马逊授权第一步 返回给前端跳转亚马逊的url
     */
    @Override
    public String authorizeNow(StoreAmazonAddReq req, Long userId, Long companyId) {
        boolean check = platformStoreService.check(req.getId(), req.getStoreCode(), companyId);
        if (!check) {
            throw new BizException(SysConstant.Shop_Code_Exist);
        }
        if (req.getId() != null) {
            PlatformStoreDo storeDo = platformStoreService.getById(req.getId());
            if (storeDo == null || !Objects.equals(storeDo.getCompanyId(), companyId)) {
                throw new BizException(SysConstant.Shop_NotExist);
            }
        }
        String state = UUID.randomUUID().toString();
        //放入缓存
        redisTemplate.opsForValue().set(AUTHORIZESTATEKEY + userId, state, 3000, TimeUnit.SECONDS);
        redisTemplate.opsForValue().set(state, JSON.toJSONString(req), 3000, TimeUnit.SECONDS);
        String url = StaticDict.PlatformOrder_Amazon_Market.getCentralUrl(req.getRegionCode()) + "apps/authorize/consent?" + "application_id=" + GlobalConstants.amazonAppId + "&state=" + state + "&redirect_uri=" + redirectURL;
//        url += "&version=beta";
        return url;
    }

    @Override
    public void getAuthorizeMsg( Map<String, String> map, Long userId, Long companyId) {
        //验证state值

        Object value = redisTemplate.opsForValue().get(map.get("state"));
        if (value == null) {
            throw new BizException(SysConstant.Store_Auth_notExistMsg);
        }
        StoreAmazonAddReq storeAmazonAddReq = JSON.parseObject(value.toString(), StoreAmazonAddReq.class);
        String sellingPartnerId = map.get("selling_partner_id");
        String mws_auth_token = map.get("mws_auth_token");

        //判断 sellingPartnerId 唯一性 todo
        //您的应用程序用 LWA 授权码交换 LWA 刷新令牌
        Map<String, String> paramMap = new HashMap<>();
        paramMap.put("grant_type", "authorization_code");
        paramMap.put("code", map.get("spapi_oauth_code"));
        paramMap.put("client_id", GlobalConstants.AmzSpClientId);
        paramMap.put("client_secret", getAmzSpClientSecret());
        paramMap.put("redirect_uri", redirectURL);

        String body = null;
        try {
            body = AmazonUtil.spAPidoPOST("https://api.amazon.com/auth/o2/token", "", "",
                    StaticDict.PlatformOrder_Amazon_Market.getRegionName(storeAmazonAddReq.getRegionCode()), paramMap, JSON.toJSONString(paramMap));
        } catch (Exception e) {
            e.printStackTrace();
        }
        //todo 看看次数能不能获取详细站点，亚马逊站点有16个
        if (body == null) {
            throw new BizException(SysConstant.User_Auth_Error);
        }
        JSONObject jsonObject = JSONObject.parseObject(body);
        if (jsonObject == null || jsonObject.getString("refresh_token") == null) {
            throw new BizException(SysConstant.User_Auth_Error);
        }
        PlatformStoreDo storeDo;
        if (storeAmazonAddReq.getId() == null) {
             storeDo = platformStoreService.amazonStoreAdd(storeAmazonAddReq, userId);
        }
        else {
             storeDo = platformStoreService.getById(storeAmazonAddReq.getId());
             if (!Objects.equals(storeDo.getCompanyId(), companyId)) {
                 throw new BizException(SysConstant.Shop_NotExist);
             }
        }
        storeDo.setSellerId(sellingPartnerId);
        storeDo.setServiceToken(mws_auth_token);
        storeDo.setAppSecret(jsonObject.getString("refresh_token"));
        storeDo.setAuthSyncStatus(1);
        storeDo.setAuthExpireTime(DateUtils.passingDateYear(new Date(), 1));
        storeDo.setAuthSyncTime(new Date());
        platformStoreDao.updateById(storeDo);
        redisTemplate.opsForValue().set(AMZACCESSTOKEN + storeDo.getId(), jsonObject.getString("access_token"), 3000, TimeUnit.SECONDS);


    }

    @Override
    public void makeShip(AmazonMarkShipConsumerReq req) {
        PlatformStoreDo storeDo = platformStoreDao.selectById(req.getStoreId());
        if (storeDo == null) {
            return;
        }
        String feedId = this.uploadFeeds(req.getMarks(), storeDo);
        List<OperateRecordDo> operateRecordDos = new ArrayList<>();
        if (StringUtils.isBlank(feedId)) {
            platformOrderService.updateMarkStatus(req.getMarks().stream().map(AmazonOrderFulfillmentEt::getId).collect(Collectors.toList()), 2, "上传模版文件失败");
            for (AmazonOrderFulfillmentEt mark : req.getMarks()) {
                OperateRecordDo operateRecordDo = new OperateRecordDo(mark.getId(), OperateTypeEnum.PlatformOrder.getValue(), SysConstant.platformOrder_MarkShip_Fail, req.getUserId(), new Date(), "上传模版文件失败");
                operateRecordDos.add(operateRecordDo);

            }
        }
        else {
            platformOrderService.updateMarkStatus(req.getMarks().stream().map(AmazonOrderFulfillmentEt::getId).collect(Collectors.toList()), 1, null);
            RakutenMarkRecordDo markRecordDo = new RakutenMarkRecordDo("amazon", feedId, storeDo.getId(), req.getUserId(), storeDo.getCompanyId());
            Long recordId = rakutenMarkRecordService.insertOne(markRecordDo);
            List<RakutenMarkRecordOrderDo> list = new ArrayList<>();
            for (AmazonOrderFulfillmentEt mark : req.getMarks()) {
                RakutenMarkRecordOrderDo rakutenMarkRecordOrderDo = new RakutenMarkRecordOrderDo(recordId, mark.getId());
                rakutenMarkRecordOrderDo.setRequestId(feedId);
                list.add(rakutenMarkRecordOrderDo);
                OperateRecordDo operateRecordDo = new OperateRecordDo(mark.getId(), OperateTypeEnum.PlatformOrder.getValue(), SysConstant.platformOrder_MarkShip_ing_No, req.getUserId(), new Date(), mark.getFulfillmentData().getShipperTrackingNumber());
                operateRecordDos.add(operateRecordDo);
            }
            rakutenMarkRecordOrderService.insertBatchMy(list);
        }
        if(!operateRecordDos.isEmpty()) {
            List<List<OperateRecordDo>> partition = ListUtil.partition(operateRecordDos, 3000);
            for (List<OperateRecordDo> partList : partition) {
                rabbitTemplate.convertAndSend(RabbitQueueConstant.CrossMall_CMOrder_OperateList, JSON.toJSONString(partList));
            }
        }
    }

    /**
     * 上传模板文件
     *
     * @param integerListEntry
     * @return
     */
    private String uploadFeeds(List<AmazonOrderFulfillmentEt> integerListEntry, PlatformStoreDo storeDo) {
        List<String> orderIds = new ArrayList<>();
        String accessToken = null;
        try {
            accessToken = getAccessToken(storeDo);
        } catch (Exception e) {
            e.printStackTrace();
        }
        if (accessToken == null) {
            return null;
        }
        String body1 = createFeedsDocuments(storeDo, "text/xml; charset=UTF-8");
        if (StringUtils.isBlank(body1)) {
            return null;
        }
        JSONObject jsonObject = JSONObject.parseObject(body1);
        if (jsonObject.getJSONArray("errors") != null) {
            if (jsonObject.getJSONArray("errors").getJSONObject(0).getString("code").equals("Unauthorized")) {
               //密钥过期
            }
            return null;
        }
        List<AmzSubmitFeedMessage> messageList = new ArrayList<>();

        for (int i = 0; i < integerListEntry.size(); i++) {
            AmzSubmitFeedMessage message = new AmzSubmitFeedMessage();
            message.setMessageID(String.valueOf(i + 1));
            message.setOperationType("Update");
            AmazonOrderFulfillmentEt fulfillmentEt = integerListEntry.get(i);

            AmazonOrderFulfillment fulfillment =  new AmazonOrderFulfillment();
            fulfillment.setAmazonOrderID(fulfillmentEt.getAmazonOrderID());
            fulfillment.setFulfillmentDate(fulfillmentEt.getFulfillmentDate());
            fulfillment.setCODCollectionMethod(fulfillmentEt.getCODCollectionMethod());
            fulfillment.setFulfillmentData(fulfillmentEt.getFulfillmentData());
            fulfillment.setItem(fulfillmentEt.getItem());
            message.setOrderFulfillment(fulfillment);
            orderIds.add(integerListEntry.get(i).getAmazonOrderID());
            messageList.add(message);
        }
        CreateFeedDocumentResult createFeedDocumentResult;
        String feedId = "";
        log.info("amazon标发开始，参数：" + JSON.toJSONString(messageList));
        try {
            createFeedDocumentResult = JSON.parseObject(jsonObject.toString(), CreateFeedDocumentResult.class);
            String body = AmazonUtil.uploadFeedsDocumentsFile(messageList, storeDo.getSellerId(), createFeedDocumentResult.getUrl(), "OrderFulfillment");
            if (StringUtils.isBlank(createFeedDocumentResult.getFeedDocumentId())) {
                return null;
            }
            feedId = createFeed(createFeedDocumentResult.getFeedDocumentId(), storeDo, "POST_ORDER_FULFILLMENT_DATA");
        } catch (Exception e) {
            e.printStackTrace();
        }
//        log.error("amazom标发结束，返回：" + feedId);
        return feedId;
    }




    @Override
    public void syncMarkRecord() {
        List<RakutenMarkRecordDo> list = rakutenMarkRecordService.list(new LambdaQueryWrapper<RakutenMarkRecordDo>()
                .eq(RakutenMarkRecordDo::getStatus, 0).eq(RakutenMarkRecordDo::getType, "amazon")
                .ge(RakutenMarkRecordDo::getCreateTime, DateUtils.dateFormatToString(DateUtils.passingDate(new Date(), -1))));
        for (RakutenMarkRecordDo markRecordDo : list) {
            rabbitTemplate.convertAndSend(RabbitQueueConstant.PlatformOrder_Amazon_MarkStatus, JSON.toJSONString(markRecordDo));
        }
    }


    @Override
    public void syncStockToPlatformRecord() {
        List<RakutenMarkRecordDo> list = rakutenMarkRecordService.list(new LambdaQueryWrapper<RakutenMarkRecordDo>()
                .eq(RakutenMarkRecordDo::getStatus, 0).eq(RakutenMarkRecordDo::getType, "amazon_stock")
                .ge(RakutenMarkRecordDo::getCreateTime, DateUtils.dateFormatToString(DateUtils.passingDate(new Date(), -1))));
        for (RakutenMarkRecordDo markRecordDo : list) {
            rabbitTemplate.convertAndSend(RabbitQueueConstant.PlatformOrder_Amazon_MarkStatus, JSON.toJSONString(markRecordDo));
        }
    }

    /**
     * 根据模板提交文件查询进度
     *
     * @return
     */
    @Override
    public String getFeed(RakutenMarkRecordDo req) {
        PlatformStoreDo storeDo = platformStoreDao.selectById(req.getStoreId());
        if (storeDo == null) {
            return null;
        }
        Map<String, Object> parametersMap = new HashMap<>();
        try {
            String result = AmazonUtil.spAPidoGet("https://sellingpartnerapi-fe.amazon.com/feeds/2021-06-30/feeds/" + req.getRequestId(),
                    getAccessToken(storeDo), getAwsSTSSessionToken(storeDo.getRegionCode()), storeDo.getRegionCode(), parametersMap);
            log.info(result);
            JSONObject jsonObject = JSON.parseObject(result);
            if (jsonObject.getJSONArray("errors") != null) {

            } else if ("DONE".equals(jsonObject.getString("processingStatus"))) {
                String resultFeedDocumentId = jsonObject.getString("resultFeedDocumentId");
                if ("amazon_stock".equals(req.getType())) {
                    getDocumentFotJson(req.getId(), resultFeedDocumentId, storeDo);
                }
                else {
                    getDocument(req.getId(), resultFeedDocumentId, storeDo, req.getType(), req.getCreateBy());
                }
            } else if ("IN_PROGRESS".equals(jsonObject.getString("processingStatus")) || "IN_QUEUE".equals(jsonObject.getString("processingStatus"))) {
            } else {

            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }


    private void getDocumentFotJson(Long id, String feedDocumentId, PlatformStoreDo storeDo) {
        Map<String, Object> parametersMap = new HashMap<>();
        String body = null;
        try {
            body = AmazonUtil.spAPidoGet("https://sellingpartnerapi-fe.amazon.com/" + "feeds/2021-06-30/documents/" + feedDocumentId,
                    getAccessToken(storeDo), getAwsSTSSessionToken(storeDo.getRegionCode()), storeDo.getRegionCode(), parametersMap);
            CreateFeedDocumentResult createFeedDocumentResult = JSON.parseObject(body, CreateFeedDocumentResult.class);
            String contentType;
            contentType = String.format("application/json; charset=%s", StandardCharsets.UTF_8);

            String downloadBody = AmazonUtil.download(createFeedDocumentResult.getUrl(), contentType, createFeedDocumentResult.getCompressionAlgorithm());
            if (StringUtils.isBlank(downloadBody)) {
                return;
            }
            JSONObject jsonObject = JSONObject.parseObject(downloadBody);
            if (jsonObject == null) {
                return ;
            }
//            log.error("amazon更新库存返回值:" + jsonObject.toJSONString());
            //{"header":{"sellerId":"A24R89N7D70DAH","version":"2.0","feedId":"419693020143"},
            // "issues":[{"code":"4002005","severity":"ERROR","message":"項目「version」は必須ですが入力されていません。"}],"summary":{"errors":1,"warnings":0,"messagesProcessed":0,"messagesAccepted":0,"messagesInvalid":0}}
            //不会返回具体哪些成功哪些失败
            RakutenMarkRecordDo recordDo = rakutenMarkRecordService.getById(id);
            if (recordDo != null) {
                recordDo.setStatus(1);
                recordDo.setRequestCount(recordDo.getRequestCount() == null ? 0 : recordDo.getRequestCount() + 1);
                //0 待请求，1请求成功 2请求不存在
                rakutenMarkRecordService.updateById(recordDo);
//                Map<Long, String> markRecordMap = rakutenMarkRecordOrderService.list(new LambdaQueryWrapper<RakutenMarkRecordOrderDo>()
//                                .select(RakutenMarkRecordOrderDo::getId, RakutenMarkRecordOrderDo::getOrderId, RakutenMarkRecordOrderDo::getMessage)
//                        .eq(RakutenMarkRecordOrderDo::getMarkId, id)).stream().collect(Collectors.toMap(RakutenMarkRecordOrderDo::getOrderId,RakutenMarkRecordOrderDo::getMessage, (v1, v2) -> v1));
//                List<OperateRecordDo> operateRecordDos = new ArrayList<>();
//                for (Long orderId : markRecordMap.keySet()) {
//                    String message = markRecordMap.get(orderId);
//                    OperateRecordDo operateRecordDo = new OperateRecordDo(orderId, OperateTypeEnum.PlatProduct_StockTO_Platform.getValue(),
//                            SysConstant.platProduct_StockTo_Platform_SUCCESS, recordDo.getCreateBy(), recordDo.getCreateTime(), message);
//                    operateRecordDos.add(operateRecordDo);
//                }
//                if (!operateRecordDos.isEmpty()) {
//                    List<List<OperateRecordDo>> recordPartition = ListUtil.partition(operateRecordDos, 3000);
//                    for (List<OperateRecordDo> partList : recordPartition) {
//                        rabbitTemplate.convertAndSend(RabbitQueueConstant.CrossMall_CMOrder_OperateList, JSON.toJSONString(partList));
//                    }
//                }

            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }


    private void getDocument(Long id, String feedDocumentId, PlatformStoreDo storeDo, String type, Long userId) {
        Map<String, Object> parametersMap = new HashMap<>();
        String body = null;
        try {
            body = AmazonUtil.spAPidoGet("https://sellingpartnerapi-fe.amazon.com/" + "feeds/2021-06-30/documents/" + feedDocumentId,
                    getAccessToken(storeDo), getAwsSTSSessionToken(storeDo.getRegionCode()), storeDo.getRegionCode(), parametersMap);
            CreateFeedDocumentResult createFeedDocumentResult = JSON.parseObject(body, CreateFeedDocumentResult.class);
            String contentType = "application/xml,charset=utf-8";
            String downloadBody = AmazonUtil.download(createFeedDocumentResult.getUrl(), contentType, createFeedDocumentResult.getCompressionAlgorithm());
            if (StringUtils.isBlank(downloadBody)) {
                return ;
            }
            JSONObject jsonObject = XmlUtils.xml2Json(downloadBody);
            if (jsonObject == null) {
                return ;
            }
            log.info("amazon标发返回值 "+feedDocumentId+" :" + jsonObject.toJSONString());
            FeedUploadResultBean bean = JSON.parseObject(jsonObject.getJSONObject("AmazonEnvelope").getJSONArray("Message").getJSONObject(0).getJSONArray("ProcessingReport").getString(0), FeedUploadResultBean.class);
            if ("Complete".equals(bean.getStatusCode())) {
                int successFulCount = Integer.parseInt(bean.getProcessingSummary().get(0).getMessagesSuccessful());
                int processCount = Integer.parseInt(bean.getProcessingSummary().get(0).getMessagesProcessed());
                int errorCount = Integer.parseInt(bean.getProcessingSummary().get(0).getMessagesWithError());
                LambdaUpdateWrapper<RakutenMarkRecordDo> markUpdateWra = new LambdaUpdateWrapper<>();
                //0 待请求，1请求成功 2请求不存在
                markUpdateWra.set(RakutenMarkRecordDo::getStatus, 1);
                markUpdateWra.eq(RakutenMarkRecordDo::getId, id);
                rakutenMarkRecordService.update(markUpdateWra);
                if ("amazon".equals(type)) {//说明是标发的文档
                    List<RakutenMarkRecordOrderDo> recordOrderDoList = rakutenMarkRecordOrderService.list(new LambdaQueryWrapper<RakutenMarkRecordOrderDo>()
                            .eq(RakutenMarkRecordOrderDo::getMarkId, id));
                    List<Long> orderId = recordOrderDoList.stream().map(RakutenMarkRecordOrderDo::getOrderId).collect(Collectors.toList());
                    List<OperateRecordDo> operateRecordDos = new ArrayList<>();
                    if (successFulCount == orderId.size()) {
                        platformOrderService.updateMarkStatus(orderId, 3, null);
                        for (Long aOrderId : orderId) {
                            OperateRecordDo operateRecordDo = new OperateRecordDo(aOrderId, OperateTypeEnum.PlatformOrder.getValue(), SysConstant.platformOrder_MarkShip_None_TrackNo, userId, new Date(), "");
                            operateRecordDos.add(operateRecordDo);
                        }
                    } else {
//                        log.error("amazon标发返回值(BEAN类):" + bean);
                        //FeedUploadResultBean(documentTransactionID=469404020245, statusCode=Complete, processingSummary=[FeedUploadResultBean.ProcessingSummaryDTO(messagesWithError=1, messagesProcessed=18, messagesSuccessful=17, messagesWithWarning=0)],
                        // Result=[FeedUploadResultBean.Result(AdditionalInfo=[FeedUploadResultBean.AdditionalInfo(AmazonOrderID=250-3323669-7906261)],
                        // ResultMessageCode=18028, ResultDescription=注文にある商品が注文番号250-3323669-7906261で見つかりません。, ResultCode=Error, MessageID=17)])

                        //失败的情况
                        //    "Message": [
                        //            {
                        //                "ProcessingReport": [
                        //                    {
                        //                        "DocumentTransactionID": "115353020370",
                        //                        "StatusCode": "Complete",
                        //                        "ProcessingSummary": [
                        //                            {
                        //                                "MessagesWithError": "1",
                        //                                "MessagesProcessed": "10",
                        //                                "MessagesSuccessful": "9",
                        //                                "MessagesWithWarning": "0"
                        //                            }
                        //                        ],
                        //                        "Result": [
                        //                            {
                        //                                "ResultMessageCode": "25",
                        //                                "ResultDescription": "We are unable to process the XML feed because one or more items are invalid. Please re-submit the feed.",
                        //                                "ResultCode": "Error",
                        //                                "MessageID": "5"
                        //                            }
                        //                        ]
                        //                    }
                        //                ],
                        //                "MessageID": "1"
                        //            }
                        //        ],

                        Map<String, Long> messageIdMap = new HashMap<>();
                        for (int i = 0; i < recordOrderDoList.size(); i++) {
                            messageIdMap.put(String.valueOf(i+1), recordOrderDoList.get(i).getOrderId());
                        }

                        List<PlatformOrderDo> platformOrderDoList = platformOrderService.list(new LambdaQueryWrapper<PlatformOrderDo>()
                                .select(PlatformOrderDo::getId, PlatformOrderDo::getPlatformOrderNo)
                                .in(PlatformOrderDo::getId, orderId));
                        Map<Long, String> amazonOrderNoMap = platformOrderDoList.stream().collect(Collectors.toMap(PlatformOrderDo::getId, PlatformOrderDo::getPlatformOrderNo));
                        //获取标发失败的
                        Map<String, List<String>> failMap = new HashMap<>();
                        for (FeedUploadResultBean.Result result : bean.getResult()) {
                            if (!"Error".equals(result.getResultCode())) {
                                continue;
                            }
                            String failReason = result.getResultDescription();
                            if (CollUtil.isEmpty(result.getAdditionalInfo())) {
                                Long failMessageId = messageIdMap.get(result.getMessageID());
                                if (failMessageId != null && amazonOrderNoMap.containsKey(failMessageId)) {
                                    failMap.computeIfAbsent(failReason, k -> new ArrayList<>()).add(amazonOrderNoMap.get(failMessageId));
                                }
                            }
                            else {
                                for (FeedUploadResultBean.AdditionalInfo additionalInfo : result.getAdditionalInfo()) {
                                    failMap.computeIfAbsent(failReason, k -> new ArrayList<>()).add(additionalInfo.getAmazonOrderID());
                                }
                            }
                        }
                        if (!failMap.isEmpty() && !orderId.isEmpty()) {
                            //通过orderId 去拿
                            Map<String, Long> orderNoMap = platformOrderDoList.stream().collect(Collectors.toMap(PlatformOrderDo::getPlatformOrderNo, PlatformOrderDo::getId, (o1, o2) -> o1));
                            for (String failReason : failMap.keySet()) {
                                List<Long> orderIdList = new ArrayList<>();
                                for (String string : failMap.get(failReason)) {
                                    if (!orderNoMap.containsKey(string)) {
                                        continue;
                                    }
                                    orderIdList.add(orderNoMap.get(string));
                                }
                                platformOrderService.updateMarkStatus(orderIdList, 2, failReason);
                                orderId.removeAll(orderIdList);
                                for (Long aOrderId : orderIdList) {
                                    OperateRecordDo operateRecordDo = new OperateRecordDo(aOrderId, OperateTypeEnum.PlatformOrder.getValue(), SysConstant.platformOrder_MarkShip_Fail, userId, new Date(), failReason);
                                    operateRecordDos.add(operateRecordDo);
                                }
                            }
                        }
                        if (!orderId.isEmpty()) {//剩下的都是标发成功的
                            platformOrderService.updateMarkStatus(orderId, 3, null);
                            for (Long aOrderId : orderId) {
                                OperateRecordDo operateRecordDo = new OperateRecordDo(aOrderId, OperateTypeEnum.PlatformOrder.getValue(), SysConstant.platformOrder_MarkShip_None_TrackNo, userId, new Date(), "");
                                operateRecordDos.add(operateRecordDo);
                            }
                        }
                    }
                    if(!operateRecordDos.isEmpty()) {
                        List<List<OperateRecordDo>> partition = ListUtil.partition(operateRecordDos, 3000);
                        for (List<OperateRecordDo> partList : partition) {
                            rabbitTemplate.convertAndSend(RabbitQueueConstant.CrossMall_CMOrder_OperateList, JSON.toJSONString(partList));
                        }
                    }
                }
            }
            return ;
        } catch (Exception e) {
            e.printStackTrace();
        }

        return;
    }

    /**
     * 把提交模板申请
     *
     * @param feedDocumentId 模板id
     * @return
     */
    private String createFeed(String feedDocumentId, PlatformStoreDo storeDo, String feedType) {
        try {
            Map<String, Object> parametersMap = new HashMap<>();
            String marketplaceId = StaticDict.PlatformOrder_Amazon_Market.getMarketplaceId(storeDo.getRegionCode());
            String endPoint = StaticDict.PlatformOrder_Amazon_Market.getEndpoint(storeDo.getRegionCode());
            List<String> marketplaceIds = new ArrayList<>();
            marketplaceIds.add(GlobalConstants.marketplaceId);
            parametersMap.put("feedType", feedType);
            parametersMap.put("marketplaceIds", marketplaceIds);
            parametersMap.put("inputFeedDocumentId", feedDocumentId);
            System.out.println(SHA256Utils.getSHA256(JSON.toJSONString(parametersMap)));
            log.info(JSONObject.toJSONString(parametersMap));
            String body = AmazonUtil.spAPidoPOST(endPoint + "/feeds/2021-06-30/feeds",
                    getAccessToken(storeDo), getAwsSTSSessionToken(storeDo.getRegionCode()), storeDo.getRegionCode(), parametersMap, JSON.toJSONString(parametersMap));
            log.info(body);
            return JSONObject.parseObject(body).getString("feedId");
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 创建feeds模板
     *
     * @return
     */
    private String createFeedsDocuments(PlatformStoreDo storeDo, String contentType) {
        try {
            Map<String, String> parametersMap = new HashMap<>();
            parametersMap.put("contentType", contentType);
            parametersMap.put("marketplaceIds", GlobalConstants.marketplaceId);
            String endPoint = StaticDict.PlatformOrder_Amazon_Market.getEndpoint(storeDo.getRegionCode());
            String body = AmazonUtil.spAPidoPOST(endPoint + "/feeds/2021-06-30/documents",
                    getAccessToken(storeDo), getAwsSTSSessionToken(storeDo.getRegionCode()),
                    StaticDict.PlatformOrder_Amazon_Market.getRegionName(storeDo.getRegionCode()), parametersMap, JSON.toJSONString(parametersMap));
            log.info(body);
            return body;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }




    /**********************************************************************库存回传至亚马逊**********************************************************/


    @Override
    public void setStockByStoreId(StockToPlatformConsumerReq req) {
        PlatformStoreDo storeDo = platformStoreDao.selectById(req.getStoreId());
        if (storeDo == null) {
            return;
        }
        AsyncJobDo asyncJobDo = asyncJobDao.selectById(req.getJobId());
        if (asyncJobDo == null) {
            return;
        }
        //告诉他正在处理
        rabbitTemplate.convertAndSend(RabbitQueueConstant.Export_AsyncDo_Update, JSON.toJSONString(new AsyncUpdateConsumerReq(req.getJobId(), 1, 0, null)));
        List<PlatformSkuStockDto> skuStockList = productStockDao.getPlatformSkuStockList(Arrays.asList(StaticDict.Store_PlatformCode.Amazon.getValue()),
                req.getPlatformSkuList(), null, req.getInventoryLink(), Arrays.asList(req.getStoreId()));
        if (skuStockList.isEmpty()) {
            rabbitTemplate.convertAndSend(RabbitQueueConstant.Export_AsyncDo_Finish, JSON.toJSONString(new AsyncFinishConsumerReq(req.getJobId(), null)));
            return;
        }
        String stockRedisKey = RedisKeyConstants.PLATFORMSTOCK_KEY_PREFIX +customer +"_"+ req.getStoreId();
        // 新增：存储SKU ID与对应库存的映射（用于ZSet的score）
        Map<Long, Integer> small20IdToQuantityMap = new HashMap<>();
        List<InventoryAmazonEntity> messageList = new ArrayList<>();
        for (PlatformSkuStockDto skuStock : skuStockList) {
            if (!"DEFAULT".equals(skuStock.getFulfillmentChannelCode())) {
                //亚马逊发货的不用管
                continue;
            }
            if (skuStock.getSystemProductId() == null) {
                continue;
            }
            double stockPercent = skuStock.getStockPercent() < 0 || skuStock.getStockPercent() > 1 ? 0.95 : 1 - skuStock.getStockPercent();
            int quantity = (int) (skuStock.getLeftQty() / skuStock.getQty() * stockPercent);
            quantity = Math.min(Math.max(quantity, 0), 99999);
            if (quantity > 0 && quantity <= 20) {
                small20IdToQuantityMap.put(skuStock.getId(), quantity); // 保存ID与库存的映射
            }
            if (quantity <= 20 && req.getUserId() == null) {
                quantity = 0;
            }
            Integer lastQuantity = platformOrderService.getLastRecordedInventory(stockRedisKey, skuStock.getPlatformSku());
            if (lastQuantity == null || !lastQuantity.equals(quantity) || req.getUserId() != null) {
                InventoryAmazonEntity message = new InventoryAmazonEntity(skuStock.getId(), skuStock.getParentSku(), skuStock.getPlatformSku(), quantity, skuStock.getShippingDayId());
                messageList.add(message);
            }
        }
        String feedId = this.uploadFeedsForInventory(messageList, storeDo, req.getUserId());
        if (StringUtils.isNotBlank(feedId)) {
            try {
                String key = asyncJobDo.getJobType() + "_count_"  + "_" + asyncJobDo.getCompanyId() + "_" + customer + "_" + DateUtils.dateFormatToString(new Date(), "yyyyMMdd");
                long count = redisTemplate.opsForValue().increment(key, 1);
                redisTemplate.expire(key, 60 * 60 * 25, TimeUnit.SECONDS);
                String fileName = asyncJobDo.getJobName() + "_" + count + ".csv";
                String tempFilePath = omsFilePath + fileName;
                CsvExportParams csvParam = new CsvExportParams();
//            csvParam.setEncoding("Shift-JIS");
                csvParam.setEncoding("UTF-8");
                csvParam.setTextMark("");
                CsvUtils.initCsv(tempFilePath, csvParam, StockToPlatformRecordVo.class);

                List<StockToPlatformRecordVo> list = new ArrayList<>();
                //记录一下 店铺 平台sku 上一次回传数量
                Map<String, String> thisStockMap = new HashMap<>();
                for (InventoryAmazonEntity mark : messageList) {
                    list.add(new StockToPlatformRecordVo(mark.getParentSku(), mark.getSku(), mark.getQuantity(), "成功", null));
                    thisStockMap.put(mark.getSku(), String.valueOf(mark.getQuantity()));
                }
                if (!thisStockMap.isEmpty() && req.getUserId() == null) {
                    //记录本次回传数量至redis
                    redisTemplate.opsForHash().putAll(stockRedisKey, thisStockMap);
//                    redisTemplate.expire(stockRedisKey, 8, TimeUnit.HOURS);
                }
                CsvUtils.appendToCsv(tempFilePath, list);
                rabbitTemplate.convertAndSend(RabbitQueueConstant.Export_AsyncDo_Update, JSON.toJSONString(new AsyncUpdateConsumerReq(req.getJobId(), null, list.size(), null)));
                //本机文件传到oms上
                String objectNameTemporary = "";
                if (filePath.startsWith("http")) {
                    try {
                        objectNameTemporary = AliOss.temporaryFile2(fileName, new File(tempFilePath));
                    } catch (Exception e) {
                        e.printStackTrace();
                        log.error("导出文件失败" + e.getMessage());
                    }
                }
                //文件路径
                String path = fileUrl + objectNameTemporary;
                rabbitTemplate.convertAndSend(RabbitQueueConstant.Export_AsyncDo_Finish, JSON.toJSONString(new AsyncFinishConsumerReq(req.getJobId(), path)));
            } catch (Exception e) {
                e.printStackTrace();
                rabbitTemplate.convertAndSend(RabbitQueueConstant.Export_AsyncDo_Update, JSON.toJSONString(new AsyncUpdateConsumerReq(req.getJobId(), 4, 0, e.getMessage())));
            }
        }
        else {
            //没有需要回传的
            rabbitTemplate.convertAndSend(RabbitQueueConstant.Export_AsyncDo_Finish, JSON.toJSONString(new AsyncFinishConsumerReq(req.getJobId(), null)));
        }
        rabbitTemplate.convertAndSend(RabbitQueueConstant.PlatformProduct_InventoryLess, JSON.toJSONString(new UpdateInventoryLessReq(req.getStoreId(), req.getUserId(), small20IdToQuantityMap)));
    }

    /**
     * 上传模板文件
     *
     * @param integerListEntry
     * @return
     */
    @Override
    public String uploadFeedsForInventory(List<InventoryAmazonEntity> integerListEntry, PlatformStoreDo storeDo, Long userId) {
        if (integerListEntry.isEmpty()) {
            return null;
        }
        String accessToken = null;
        try {
            accessToken = getAccessToken(storeDo);
        } catch (Exception e) {
            e.printStackTrace();
        }
        if (accessToken == null) {
            return null;
        }
        String contentType = String.format("application/json; charset=%s", StandardCharsets.UTF_8);

        String body1 = createFeedsDocuments(storeDo, contentType);
        if (StringUtils.isBlank(body1)) {
            return null;
        }
        JSONObject jsonObject = JSONObject.parseObject(body1);
        if (jsonObject.getJSONArray("errors") != null) {
            if (jsonObject.getJSONArray("errors").getJSONObject(0).getString("code").equals("Unauthorized")) {
                //密钥过期
            }
            return null;
        }
        Map<String, Object> keys = redisTemplate.opsForHash().entries(RedisKeyConstants.PlatformSku_ProductType + storeDo.getSellerId());
        if (keys.isEmpty()) {
            keys = this.syncListingsItems(storeDo, null);
        }
        List<Message> messageList = new ArrayList<>();
        InventoryUpdateMessageJson jsonFeed = new InventoryUpdateMessageJson();
        for (int i = 0; i < integerListEntry.size(); i++) {
            Message message = new Message();
            message.setMessageId(i + 1);
            message.setSku(integerListEntry.get(i).getSku());
            message.setOperationType("PARTIAL_UPDATE");
            if (keys.get(message.getSku()) == null) {
                continue;
            }
            String productType = keys.get(message.getSku()).toString();
            String[] split = productType.split("-----");
            message.setProductType(split[0]);//DEFAULT
            Attributes attributes = new Attributes();
            FulfillmentAvailability availability = new FulfillmentAvailability();
            availability.setQuantity(integerListEntry.get(i).getQuantity());
            availability.setFulfillment_channel_code(split[1]);
            if (!Objects.equals("-1", integerListEntry.get(i).getLeadTimeToShipMaxDays())) {
                availability.setLead_time_to_ship_max_days(integerListEntry.get(i).getLeadTimeToShipMaxDays());
            }
            attributes.setFulfillment_availability(Collections.singletonList(availability));
            message.setAttributes(attributes);
            messageList.add(message);
        }
        if (messageList.isEmpty()) {
            return null;
        }
        jsonFeed.setMessages(messageList);
        jsonFeed.setHeader(new Header(storeDo.getSellerId(), "2.0", "en_US"));
//        log.error("亚马逊更新库存传值：\r\n" + JSONObject.toJSONString(jsonFeed));
        CreateFeedDocumentResult createFeedDocumentResult;
        String feedId = "";
        try {
            createFeedDocumentResult = JSON.parseObject(jsonObject.toString(), CreateFeedDocumentResult.class);
            if (StringUtils.isBlank(createFeedDocumentResult.getFeedDocumentId())) {
                return null;
            }
            boolean b = AmazonUtil.uploadJSON(JSONObject.toJSONString(jsonFeed).getBytes(StandardCharsets.UTF_8), createFeedDocumentResult.getUrl());
            if (!b) {
                return null;
            }
            feedId = createFeed(createFeedDocumentResult.getFeedDocumentId(), storeDo, "JSON_LISTINGS_FEED");
//            getFeed(feedId, orderIds, storeDo);
//            return createFeedDocumentResult.getFeedDocumentId();
        } catch (Exception e) {
            e.printStackTrace();
        }
        if (StringUtils.isNotBlank(feedId)) {
            RakutenMarkRecordDo markRecordDo = new RakutenMarkRecordDo("amazon_stock", feedId, storeDo.getId(), userId, storeDo.getCompanyId());
            Long recordId = rakutenMarkRecordService.insertOne(markRecordDo);
            List<RakutenMarkRecordOrderDo> list = new ArrayList<>();
            for (InventoryAmazonEntity mark : integerListEntry) {
                String message = StaticDict.Store_PlatformCode.Amazon.getValue() + SysConstant.operateRecordSeparator + storeDo.getStoreName() + SysConstant.operateRecordSeparator
                        + mark.getParentSku() + SysConstant.operateRecordSeparator + mark.getSku() + SysConstant.operateRecordSeparator + mark.getQuantity();
                list.add(new RakutenMarkRecordOrderDo(recordId, mark.getId(), message));
            }
            rakutenMarkRecordOrderService.insertBatchMy(list);
        }
        return feedId;
    }


    @Override
    public void amazonGetItemList() {
        List<PlatformStoreDo> storeDoList = platformStoreDao.selectList(new LambdaQueryWrapper<PlatformStoreDo>().eq(PlatformStoreDo::getPlatformCode, "amazon")
                .eq(PlatformStoreDo::getAuthSyncStatus, 1).isNotNull(PlatformStoreDo::getAppSecret));
        for (PlatformStoreDo platformStoreDo : storeDoList) {
            rabbitTemplate.convertAndSend(RabbitQueueConstant.GetPlatformProduct_Amazon, JSON.toJSONString(new AmazonItemConsumerReq(platformStoreDo, null)));
        }
    }

    @Override
    public Map<String, Object> syncListingsItems(PlatformStoreDo storeDo, String packageHierarchySku) {
        if (storeDo == null || StringUtils.isBlank(storeDo.getSellerId())) {
            return new HashMap<>();
        }
        String key = RedisKeyConstants.PlatformProduct_Sync_Flag_ +customer+ storeDo.getId();
        Object o = redisTemplate.opsForValue().get(key);
        if (o != null) {
            return new HashMap<>();
        }
        redisTemplate.opsForValue().set(key, 1, 10, TimeUnit.MINUTES);
        String nextToken = "";
        Map<String, Object> params = new HashMap<>();
        params.put("marketplaceIds", "A1VC38T7YXB528");
        params.put("pageSize", 20);
        params.put("includedData", StringUtils.join(Arrays.asList("summaries", "attributes", "issues", "offers", "fulfillmentAvailability", "productTypes", "procurement", "relationships"), ","));
        params.put("sortBy", "lastUpdatedDate");
        params.put("sortOrder", "DESC");
        if (StringUtils.isNotBlank(packageHierarchySku)) {
            params.put("packageHierarchySku", packageHierarchySku);
        }
//        params.put("withStatus", "BUYABLE");
        String endPoint = StaticDict.PlatformOrder_Amazon_Market.getEndpoint(storeDo.getRegionCode());
        String accessToken = getAccessToken(storeDo);
        Map<String, Object> asinProductTypeMap = new HashMap<>();
        List<PlatformProductDo> platformProductDoList = new ArrayList<>();
        do {
            if (StringUtils.isNotBlank(nextToken)) {
                params.put("pageToken", nextToken);
            }
            String result = AmazonUtil.spAPidoGet(endPoint + "/listings/2021-08-01/items/"+ storeDo.getSellerId(), accessToken, getAwsSTSSessionToken(storeDo.getRegionCode()), StaticDict.PlatformOrder_Amazon_Market.getRegionName(storeDo.getRegionCode()), params);
            JSONObject jsonObject = JSON.parseObject(result);
            if (jsonObject.getJSONArray("errors") != null) {
                log.error(jsonObject.getJSONArray("errors").toJSONString());
                //如果同步失败则 将上一次同步时间更新到以前
                log.error("获取 amazon商品 productTypes 错误：" + jsonObject.getJSONArray("errors").toJSONString());
                return new HashMap<>();
            }
            ListingItemResponse orderReponse = JSONObject.parseObject(jsonObject.toString(), ListingItemResponse.class);
            for (ListingItemEntity item : orderReponse.getItems()) {
//                if (item.getProductTypes() == null || item.getProductTypes().isEmpty()) {
//                    continue;
//                }
                String productType = "";
                if (item.getProductTypes() != null && !item.getProductTypes().isEmpty()) {
                    productType = item.getProductTypes().get(0).getProductType();
                }
                String ful = "DEFAULT";
                if (!item.getFulfillmentAvailability().isEmpty()) {
                    ful = item.getFulfillmentAvailability().get(0).getFulfillmentChannelCode();
                }
                Integer handleTime = -1;
                if (item.getAttributes() != null && !CollUtil.isEmpty(item.getAttributes().getFulfillment_availability())) {
                    if (item.getAttributes().getFulfillment_availability().get(0).getLeadTimeToShipMaxDays() != null) {
                        handleTime = item.getAttributes().getFulfillment_availability().get(0).getLeadTimeToShipMaxDays();
                    }
                }
                asinProductTypeMap.put(item.getSku(), productType + "-----" + ful);
                PlatformProductDo productDo = new PlatformProductDo();
                productDo.setStoreId(storeDo.getId());
                productDo.setCompanyId(storeDo.getCompanyId());
                productDo.setTenantId(storeDo.getTenantId());
                productDo.setPlatformSku(item.getSku());
                productDo.setHideItem(0);
                productDo.setShippingDayId(handleTime+"");
                productDo.setProductType(productType);
                productDo.setFulfillmentChannelCode(ful);
//                productDo.setPlatLeftQuantity(quantity);
                if (item.getRelationships() != null && !item.getRelationships().isEmpty()) {
                    if (item.getRelationships().get(0).getRelationships() != null && !item.getRelationships().get(0).getRelationships().isEmpty()) {
                        if (item.getRelationships().get(0).getRelationships().get(0).getParentSkus() != null && !item.getRelationships().get(0).getRelationships().get(0).getParentSkus().isEmpty()) {
                            productDo.setParentSku(item.getRelationships().get(0).getRelationships().get(0).getParentSkus().get(0));
                        }
                    }
                }
                if (item.getSummaries() != null && !item.getSummaries().isEmpty()) {
                    if (CollUtil.isEmpty(item.getSummaries().get(0).getStatus())) {
                        productDo.setHideItem(1);
                    }
                    else {
                        if (item.getSummaries().get(0).getStatus().contains("BUYABLE")) {
                            productDo.setHideItem(0);
                        }
                        else {
                            productDo.setHideItem(1);
                        }
                    }
                    productDo.setAsin(item.getSummaries().get(0).getAsin());
                    productDo.setFnSku(item.getSummaries().get(0).getFnSku());
                    productDo.setItemName(item.getSummaries().get(0).getItemName());
                    if (item.getSummaries().get(0).getMainImage() != null) {
                        productDo.setImageUrl(item.getSummaries().get(0).getMainImage().getLink());
                    }
                }
//                if (StringUtils.isBlank(productDo.getParentSku())) {
//                    continue;
//                }
                platformProductDoList.add(productDo);
            }
            if (orderReponse.getPagination() != null) {
                nextToken = orderReponse.getPagination().getNextToken();
            }
        } while (StringUtils.isNotBlank(nextToken));
        platformProductService.save(platformProductDoList, StaticDict.Store_PlatformCode.Amazon.getValue(), false, storeDo.getId(), storeDo.getCompanyId());
        //保存到redis
        redisTemplate.opsForHash().putAll(RedisKeyConstants.PlatformSku_ProductType + storeDo.getSellerId(), asinProductTypeMap);
        redisTemplate.expire(RedisKeyConstants.PlatformSku_ProductType+ storeDo.getSellerId(), 60 * 60 * 30, TimeUnit.SECONDS);
        redisTemplate.delete(key);
        return asinProductTypeMap;
    }


    /**
     * 新版本同步订单
     */
    public void platOrderAmazonSyncNew() {
        //此时就确定同步时间
        List<PlatformStoreDo> storeDoList = platformStoreDao.selectList(new LambdaQueryWrapper<PlatformStoreDo>().eq(PlatformStoreDo::getPlatformCode, "amazon")
                .eq(PlatformStoreDo::getAuthSyncStatus, 1).isNotNull(PlatformStoreDo::getAppSecret));
        if (storeDoList.isEmpty()) {
            return;
        }
        Date endTime = new Date();
        for (PlatformStoreDo storeDo : storeDoList) {
            //增量订单的上一次同步记录 亚马逊自动是更新最后更新时间同步 所以只需要上一次同步成功的时间
            PlatformOrderSyncRecordDo lastRecordDo = platformOrderSyncRecordDao.selectOne(new LambdaQueryWrapper<PlatformOrderSyncRecordDo>()
                    .eq(PlatformOrderSyncRecordDo::getStoreId, storeDo.getId())
                    .eq(PlatformOrderSyncRecordDo::getSyncStatus, 3).eq(PlatformOrderSyncRecordDo::getSyncType, 0).last(" order by end_time desc limit 1"));
            PlatformOrderSyncRecordDo newRecordDo = new PlatformOrderSyncRecordDo(storeDo.getPlatformCode(), storeDo.getId(), 0, 0, 0, new Date(), null, storeDo.getCompanyId());
            //不管有没有成功，都获取
            if (lastRecordDo == null) {
                newRecordDo.setBeginTime(DateUtils.passingDate(endTime, -1));
            }
            else {
                newRecordDo.setBeginTime(DateUtils.passingDateSec(lastRecordDo.getEndTime(), -1));
            }
            newRecordDo.setEndTime(endTime);
            platformOrderSyncRecordDao.insert(newRecordDo);
            PlatStoreConsumerReq consumerReq = new PlatStoreConsumerReq(storeDo.getId(), null, null, null, false);
            rabbitTemplate.convertAndSend(RabbitQueueConstant.PlatformStore_Amazon, JSON.toJSONString(consumerReq));
        }
    }



    public String updateAmazonOrdersNew(Long recordId) {
        PlatformOrderSyncRecordDo recordDo = platformOrderSyncRecordDao.selectById(recordId);
        if (recordDo == null) {
            return "同步记录不存在";
        }
        String failReason = null;
        PlatformStoreDo storeDo = platformStoreDao.selectById(recordDo.getStoreId());
        if (storeDo == null || StringUtils.isBlank(storeDo.getSellerId())) {
            failReason = "店铺对应平台Token未绑定";
            platformOrderSyncRecordService.updateRecord(recordId, 3, failReason);
            return failReason;
        }
        long l = DateUtil.betweenDay(recordDo.getBeginTime(), recordDo.getEndTime(), true);
        if (l > 1) {
            recordDo.setBeginTime((DateUtils.passingDate(new Date(), -1)));
        }

        String nextToken = "";
        Map<String, Object> params = new HashMap<>();
        params.put("MarketplaceIds", StaticDict.PlatformOrder_Amazon_Market.getMarketplaceId(storeDo.getRegionCode()));
        String endPoint = StaticDict.PlatformOrder_Amazon_Market.getEndpoint(storeDo.getRegionCode());
        String accessToken = getRDTAccessToken(storeDo);
        if (StringUtils.isBlank(accessToken)) {
            failReason = "accessToken 获取失败";
            platformOrderSyncRecordService.updateRecord(recordId, 3, failReason);
            return failReason;
        }
        params.put("LastUpdatedAfter", TimeUtils.formatDate(recordDo.getBeginTime(), GlobalConstants.TIME_FORMAT_STR, "GMT"));

        List<OrdersEntitySP> orders = new ArrayList<>();
        do {
            if (StringUtils.isNotBlank(nextToken)) {
                params.put("NextToken", nextToken);
            }
            String result = AmazonUtil.spOrderList(endPoint + "/orders/v0/orders", accessToken, getAwsSTSSessionToken(storeDo.getRegionCode()), storeDo.getRegionCode(), params);
            JSONObject jsonObject = JSON.parseObject(result);
            if (jsonObject.getJSONArray("errors") != null) {
                //如果同步失败则 将上一次同步时间更新到以前
                failReason = jsonObject.getJSONArray("errors").toJSONString();
                platformOrderSyncRecordService.updateRecord(recordId, 3, failReason);
//                return (jsonObject.getJSONArray("errors").toJSONString());
                break;
            }
            //主表对象
            ListOrdersResultEntitySP orderReponse = JSONObject.parseObject(jsonObject.get("payload").toString(), ListOrdersResultEntitySP.class);
            orders.addAll(new ArrayList<>(orderReponse.getOrders().stream().filter(o -> !o.getOrderStatus().equals("Pending")).collect(Collectors.toList())));
            nextToken = orderReponse.getNextToken();
        } while (StringUtils.isNotBlank(nextToken));


        return null;
    }
}
